import logging

import pandas as pd
from sklearn.linear_model import LinearRegression
from sklearn.metrics import max_error, mean_absolute_error, r2_score
from sklearn.model_selection import train_test_split

# 将数据拆分为训练集和测试集
def split_data(data: pd.DataFrame, parameters: dict) -> tuple:
    """Splits data into features and targets training and test sets.

    Args:
        data: Data containing features and target.
        parameters: Parameters defined in parameters/data_science.yml.
    Returns:
        Split data.
    """
    # 就是我要用这些数据列去预测price（y）. 
    # 这是pandas的DataFrame切片操作 df[['col1', 'col2']]
    X = data[parameters["features"]] 

    # 这是我要预测的目标, 这也是pandas的切片操作 df['col']，得到一个 Series
    y = data["price"] 

    # train_test_split 方法来自于第三方库 sklearn.model_selection
    # 它的作用是将数据集划分为训练集和测试集，以便用于机器学习模型的训练和评估。
    X_train, X_test, y_train, y_test = train_test_split( # 这个方法会返回四个值
        X, y, test_size=parameters["test_size"], random_state=parameters["random_state"]
    )
    return X_train, X_test, y_train, y_test

# 训练模型
def train_model(X_train: pd.DataFrame, y_train: pd.Series) -> LinearRegression:
    """Trains the linear regression model.

    Args:
        X_train: Training data of independent features.
        y_train: Training data for price.

    Returns:
        Trained model. 返回训练好的模型
    """

    # 这两行代码就是调用scikit-learn 库里写好的线性回归算法，让它自动帮你“训练”模型
    # 所谓训练模型 也就是自动帮你找到最合适的参数（权重和偏置），让公式能最好地拟合你的数据。
    regressor = LinearRegression()
    regressor.fit(X_train, y_train)
    """
    线性回归会“学习”这些特征和价格之间的关系，找出一个参数最合适的公式：
    price = w1 * engines + w2 * passenger_capacity + w3 * crew + ... + b
    w1, w2, w3... 是每个特征的权重（模型自动学出来的） b 是偏置（截距）
    这个公式就是“线性”的，因为每个特征都是一次方
    """
    return regressor # 返回训练好的模型

# 评估(测试)模型
def evaluate_model(
    regressor: LinearRegression, X_test: pd.DataFrame, y_test: pd.Series
) -> dict[str, float]:
    """Calculates and logs the coefficient of determination.

    Args:
        regressor: Trained model. # 传入训练好的模型
        X_test: Testing data of independent features. # 传入测试集的特征
        y_test: Testing data for price. # 传入测试集的真实价格
    """
    y_pred = regressor.predict(X_test) # 用训练好的模型来预测价格
    # 下面三行 都是在对比“真实”的结果，和预测的结果。分别算了三个指标，用于评估模型好坏
    score = r2_score(y_test, y_pred) # 计算 R^2 分数（拟合优度）
    mae = mean_absolute_error(y_test, y_pred) # 计算平均绝对误差
    me = max_error(y_test, y_pred) # 计算最大误差
    logger = logging.getLogger(__name__)
    logger.info("Model has a coefficient R^2 of %.3f on test data.", score)
    logger.info("Model has a mean absolute error of %.3f on test data.", mae)
    logger.info("Model has a max error of %.3f on test data.", me)
    return {"r2_score": score, "mae": mae, "max_error": me}
